package io.github.shoothzj.ignite.prometheus.exporter.vertx;

import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;
import org.apache.ignite.spi.IgniteSpiAdapter;
import org.apache.ignite.spi.IgniteSpiException;
import org.apache.ignite.spi.metric.Metric;
import org.apache.ignite.spi.metric.MetricExporterSpi;
import org.apache.ignite.spi.metric.ReadOnlyMetricManager;
import org.apache.ignite.spi.metric.ReadOnlyMetricRegistry;
import org.jetbrains.annotations.Nullable;

import java.util.function.Predicate;

public class PrometheusMetricsExporter extends IgniteSpiAdapter implements MetricExporterSpi {
    private ReadOnlyMetricManager metricManager;
    private Predicate<ReadOnlyMetricRegistry> exportFilter;

    public PrometheusMetricsExporter() {
        Vertx vertx = Vertx.vertx();
        HttpServer server = vertx.createHttpServer();

        Router router = Router.router(vertx);

        router.route("/metrics").handler(routingContext -> {
            HttpServerResponse response = routingContext.response();
            response.putHeader("content-type", "text/plain; version=0.0.4; charset=utf-8");
            if (this.metricManager != null) {
                StringBuilder metricsData = new StringBuilder();

                for (ReadOnlyMetricRegistry metrics : this.metricManager) {
                    for (Metric metric : metrics) {
                        String metricName = metric.name();
                        String metricValue = metric.getAsString();

                        // check if value can covert to double
                        try {
                            if (metricValue != null) {
                                Double.parseDouble(metricValue);
                            }
                        } catch (NumberFormatException e) {
                            continue;
                        }

                        metricsData.append("# TYPE ").append(metricName).append(" gauge\n");
                        metricsData.append(metricName).append(" ").append(metricValue).append("\n");
                    }
                }
                response.end(metricsData.toString());
            } else {
                response.setStatusCode(500).end("No metric manager found");
            }
        });

        server.requestHandler(router);

        server.listen(11800, "localhost", ar -> {
            if (ar.succeeded()) {
                System.out.println("Vert.x Server started on port 11800");
            } else {
                System.err.println("Vert.x Server failed to start: " + ar.cause());
            }
        });
    }

    @Override
    public void setMetricRegistry(ReadOnlyMetricManager registry) {
        this.metricManager = registry;
    }

    @Override
    public void setExportFilter(Predicate<ReadOnlyMetricRegistry> filter) {
        this.exportFilter = filter;
    }

    @Override
    public void spiStart(@Nullable String igniteInstanceName) throws IgniteSpiException {
    }

    @Override
    public void spiStop() throws IgniteSpiException {
    }
}
